package com.zjn.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    /*三个的创建顺序为由下到上，逐个创建上调用下*/

    //第三步：ShiroFilterFactoryBean
    /*
     * 将DefaultWebSecurityManager注入到这个类需要通过参数传递
     * 而参数需要通过@Qualifier指定到底是哪一个bean
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager defaultWebSecurityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //关联DefaultWebSecurityManager,设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        //自定义一个拦截器实现多perms认证，不设置就是使用默认的拦截器
        Map<String, Filter> filters = new HashMap<>();
        filters.put("permission", new PermissionsAuthorizationFilter());
        shiroFilterFactoryBean.setFilters(filters);

        /*添加shiro的内置过滤器
         *   anon：无需认证就能访问
         *   authc：必须认证了才能访问
         *   user：必须拥有 记住我 功能才能使用
         *   perms：拥有对某个资源的权限才能访问
         *   role：拥有某个角色权限才能访问
         */
        //拦截功能实现
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //允许静态资源匿名访问
        filterChainDefinitionMap.put("/static/**", "anon");
        //所有的druid请求，不需要拦截，anon对应的拦截器不会进行拦截
        filterChainDefinitionMap.put("/druid/**", "anon");
        //让index.html被所有人访问
        filterChainDefinitionMap.put("/", "anon");
        filterChainDefinitionMap.put("/index", "anon");
        filterChainDefinitionMap.put("/login/toLogin", "anon");
        /*授权
         *   未授权情况下，没有授权就会跳到指定页面
         *   这里设定需要有"user:*"字符串的用户才能访问/'*'/'*'请求
         *   注意：perms必须要放在authc前才能生效
         * */
        /*员工管理页面：
        *   list：所有人
        *   add和update：admin和manager
        *   delete：admin*/
        filterChainDefinitionMap.put("/user/userAdd", "permission[user:admin,user:manager]");
        /*filterChainDefinitionMap.put("/user/userAdd", "perms[user:manager]");*/
        filterChainDefinitionMap.put("/user/userUpdate/*", "permission[user:admin,user:manager]");
        /*filterChainDefinitionMap.put("/user/userUpdate/*", "perms[user:manager]");*/
        /*供应商管理界面：
        *   list：所有人
        *   add和update：admin和manager
        *   delete：admin和manager*/
        filterChainDefinitionMap.put("/pro/proAdd", "permission[user:admin,user:manager]");
        /*filterChainDefinitionMap.put("/pro/proAdd", "perms[user:manager]");*/
        filterChainDefinitionMap.put("/pro/proUpdate/*", "permission[user:admin,user:manager]");
        /*filterChainDefinitionMap.put("/pro/proUpdate/*", "perms[user:manager]");*/
        /*订单管理界面：
        *   list：所有人
        *   add和update：所有人
        *   delete：admin和manager*/

        /*职位管理界面：
        *   只有管理员可以进入*/
        filterChainDefinitionMap.put("/role/list","perms[user:admin]");

        //设置/user,pro,bill,role下的所有请求只有认证了才能访问
        filterChainDefinitionMap.put("/user/*", "authc");
        filterChainDefinitionMap.put("/pro/*", "authc");
        filterChainDefinitionMap.put("/bill/*", "authc");
        filterChainDefinitionMap.put("/role/*", "authc");

        /*注销功能由shiro来完成而不是用户自定义*/
        filterChainDefinitionMap.put("/login/logout", "logout");

        //设置登录请求,如果被拦截就会自动跳到这个页面
        shiroFilterFactoryBean.setLoginUrl("/login/toLogin");
        //设置未授权页面toUnauthorized
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }


    //第二步：DefaultWebSecurityManager
    /*
     * 将userRealm注入到这个类需要通过参数传递
     * 而参数需要通过@Qualifier指定到底是哪一个bean
     */
    @Bean(name = "manager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm,
                                                                  CacheManager cacheManager,
                                                                  RememberMeManager manager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setCacheManager(cacheManager);
        //记住Cookie
        securityManager.setRememberMeManager(manager);
        //关联userRealm
        securityManager.setRealm(userRealm);
        return securityManager;
    }

    /*记住我的配置*/
    @Bean
    public RememberMeManager rememberMeManager() {
        Cookie cookie = new SimpleCookie("rememberMe");
        cookie.setHttpOnly(true);//通过js脚本将无法读取到cookie信息
        cookie.setMaxAge(60 * 60 * 24);//cookie保存一天
        CookieRememberMeManager manager = new CookieRememberMeManager();
        manager.setCookie(cookie);
        return manager;
    }

    /*缓存配置*/
    @Bean
    public CacheManager cacheManager() {
        MemoryConstrainedCacheManager cacheManager = new MemoryConstrainedCacheManager();//使用内存缓存
        return cacheManager;
    }


    //第一步：创建realm对象，需要自定义类
    /*将UserRealm作为一个Bean放入spring中
     * userRealm就是这个类的别名*/
    @Bean(name = "userRealm")
    public UserRealm userRealm() {
        return new UserRealm();
    }

    /*整合ShiroDialect：用来整合shiro thymeleaf*/
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }


}
